﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;

namespace GeneratorLib.DB.Schemas
{

 

    public class FieldInfo
    {

        public TableInfo Table { get; set; }
        public string FieldName { get; set; }
        public FieldType FieldType { get; set; }
        public string FieldSize
        {
            get
            {
                if (this.FieldSize1 == 0)
                {
                    return "";
                }
                else
                {
                    if (this.FieldSize2 == 0)
                        return string.Format("{0}", this.FieldSize1);
                    else
                        return string.Format("{0},{1}", this.FieldSize1, this.FieldSize2);
                }
            }
        }

        public string FieldNameForParam
        {
            get { return GetCamaraName(this.FieldName); }
        }

        public string FieldNameForPrivateField
        {
            get { return GetCamaraName(this.FieldName); }
        }

        public string FieldNameForClassPrivateField
        {
            get { return string.Format("_{0}", GetCamaraName(this.FieldName)); }
        }

        public int FieldSize1 { get; set; }
        public int FieldSize2 { get; set; }
        public bool Nullabled { get; set; }
        public bool Key { get; set; }
        public string Comment { get; set; }
        public string DefaultValue { get; set; }


        public override string ToString()
        {
            return FieldName;
        }

        private string GetCamaraName(string fieldName)
        {
            if (fieldName.Length > 1)
            {
                return fieldName.Substring(0, 1).ToLower() + fieldName.Substring(1);
            }
            else
            {
                return fieldName.ToLower();
            }
        }

        public string GetFieldType()
        {

            string DBTypeMapping = this.Table.Connection.DBTypeMapping;
            DataRow[] rows = DBTypeMapConfig.Instance.DBTypeMap.Tables[DBTypeMapping].Select(string.Format("key='{0}'", this.FieldType.TypeName));
            if (rows.Length > 0)
            {
                if ( rows[0].Table.Columns.Contains("DBType") && rows[0]["DBType"] != null && !string.IsNullOrEmpty(rows[0]["DBType"].ToString()))
                    return string.Format("{0}", rows[0]["DBType"]);
                else
                    return string.Format("{0}", rows[0]["key"]);
            }
            else
            {
                return this.FieldType.TypeName;
            }
        }

        public void SetFieldType(string fieldType)
        {
            string DBTypeMapping = this.Table.Connection.DBTypeMapping;
            string typeName = FieldUtility.GetFieldName(fieldType);

            DataRow[] rows = DBTypeMapConfig.Instance.DBTypeMap.Tables[DBTypeMapping].Select(string.Format("key='{0}'", typeName));
            if (rows.Length > 0)
            {
                FieldType ft = new FieldType();
                ft.TypeName = string.Format("{0}", rows[0]["key"]);
                ft.MapName = string.Format("{0}", rows[0]["value"]);
                this.FieldType = ft;
            }
            else
            {
                FieldType ft = new FieldType();
                ft.TypeName = typeName;
                ft.MapName = "string";
                this.FieldType = ft;
                
            }

            string typeSize = FieldUtility.GetFieldSize(fieldType);
            if (typeSize.Trim().Length > 0)
            {
                string[] typeSizes = typeSize.Split(new char[] { ',' });
                this.FieldSize1 = Convert.ToInt32(typeSizes[0]);
                if (typeSizes.Length == 2)
                {
                    this.FieldSize2 = Convert.ToInt32(typeSizes[1]);
                }
            }
            else
            {
                this.FieldSize1 = 0;
                this.FieldSize2 = 0;
            }
        }

        public string GetNullabledDeclareTypeName()
        {
            string typeName = "";
            switch (this.FieldType.MapName.ToLower())
            {
                case "int":
                    if (this.Nullabled)
                        typeName = "int?";
                    else
                        typeName = "int";
                    break;
                case "datetime":
                    if (this.Nullabled)
                        typeName = "DateTime?";
                    else
                        typeName = "DateTime";
                    break;
                case "decimal":
                    if (this.Nullabled)
                        typeName = "decimal?";
                    else
                        typeName = "decimal";
                    break;
                case "bool":
                    typeName = "bool";
                    break;
                case "string":
                    typeName = "string";
                    break;
                default:
                    break;
            }

            return typeName;
        }

        public bool GetCSharpTypeNullable()
        {
            bool nullabletype = false;
            switch (this.FieldType.MapName.ToLower())
            {
                case "int":
                    if (this.Nullabled)
                        nullabletype =true;
                    else
                        nullabletype = false;
                    break;
                case "datetime":
                    if (this.Nullabled)
                        nullabletype = true;
                    else
                        nullabletype = false;
                    break;
                case "decimal":
                    if (this.Nullabled)
                        nullabletype = true;
                    else
                        nullabletype = false;
                    break;
                case "bool":
                    nullabletype = false;
                    break;
                case "string":
                    nullabletype = false;
                    break;
                default:
                    break;
            }

            return nullabletype;

        }


        public string GetDefaultValue()
        {
            return GetDefaultValue(false);
        }
        public string GetDefaultValue(bool chkNullabled)
        {
            string defaultValue = "";
            switch (this.FieldType.MapName.ToLower())
            {
                case "int":
                case "int16":
                case "int32":
                case "int64":
                    defaultValue = "0";
                    break;
                case "datetime":
                    if (chkNullabled && this.Nullabled && this.FieldType.MapName.ToLower().CompareTo("datetime") == 0)
                        defaultValue = "\"\"";
                    else
                        defaultValue = "DateTime.Now";
                    break;
                case "decimal":
                    defaultValue = "0";
                    break;
                case "bool":
                    defaultValue = "false";
                    break;
                case "string":
                    defaultValue = "\"\"";
                    break;
                case "double":
                    defaultValue = "0";
                    break;
                default:
                    defaultValue = "null";
                    break;
            }

            return defaultValue;
       
        }

    }

    public class FieldUtility
    {
        public static string GetFieldName(string fieldType)
        { 
            string pattern= @"[a-zA-Z_]\w*(?=\(\d+\))?";
            System.Text.RegularExpressions.Regex reg= new System.Text.RegularExpressions.Regex(pattern);
            System.Text.RegularExpressions.Match match = reg.Match(fieldType);
            if (match.Success)
                return match.Value;
            else
                return fieldType;
        }

        public static string GetFieldSize(string fieldType)
        {
            string pattern = @"(?<=[a-zA-Z_]\w*\()[\d,]+";
            System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(pattern);
            System.Text.RegularExpressions.Match match = reg.Match(fieldType);
            if (match.Success)
                return match.Value;
            else
                return "";
        }

        public static string GetDisplayName(string displayInfo)
        {
            string pattern = @".*(?=[\(（])";
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(pattern);
            System.Text.RegularExpressions.Match match = regex.Match(displayInfo);
            if (match.Success)
                return match.Value.Trim();
            else
                return displayInfo.Trim();
        }



    }

}
